<?php
namespace Common\Model;

class ZoneStatsModel extends Model {
    protected $tableName  = 'template.zone_stats';
    private   $tableName2 = 'zone_stats';

    const TABLE_PARTITION_NUM = 5;  //表格分割数量

    /**
     * _parseOptions
     * 拦截_parseOptions主要是为了自动生成表名
     * 生成表名时必须用到的参数有day和uid,也就是where()的条件必须要有day和uid
     *
     * @param mixed $options
     * @return void
     */
    protected function _parseOptions($options = null) {
        if(isset($this->options['where']['day']) && $this->options['where']['day'][0] == 'between') {
            if($this->options['where']['day'][1][0] == $this->options['where']['day'][1][1]) {
                $this->options['where']['day'] = $this->options['where']['day'][1][0];
            }
        }

        if(!empty($this->options['where']['day']) || empty($this->trueTableName) || ($this->trueTableName == $this->tableName)) {
            $loginUser = C('RUN_LOGIN_USER');
            $options   = is_array($options) ? array_merge($this->options, $options) : $this->options;

            /**
             * 为站长平台绑定站长编号
             */
            if($loginUser['type'] == 1) {
                $options['where']['uid']       = $loginUser['id'];
                $this->options['where']['uid'] = $loginUser['id'];
            }

            $day = $options['where']['day'];
            $uid = $options['where']['uid'];

            if(empty($day) || empty($uid)) {
                throw new \Exception('请确认是否有day或uid');
            }

            if($this->options['where']['day'][0] == 'between') {
                $this->parseDayBetween($this->options);

                unset($this->options['where']['uid']);
                unset($options['where']['uid']);
            } else {
                $tableName = $this->getTableName($uid, $day);

                /**
                 * 重写field中的day字段
                 */
                $tmpFields = explode(',', $options['field']);

                if(($tmpKey = array_search('day', $tmpFields)) !== false) {
                    unset($tmpFields[$tmpKey]);
                    $tmpFields[] = "'{$day}' AS day";
                    $options['field'] = implode(',', $tmpFields);
                }

                /**
                 * 去掉order中的day字段，因为不存在day字段
                 */
                if(!empty($options['order'])) {
                    $tmpOrders = explode(',', $options['order']);

                    foreach($tmpOrders as $k => $v) {
                        if(stripos($v, 'day') !== false) {
                            unset($tmpOrders[$k]);
                            break;
                        }
                    }

                    $options['order'] = empty($tmpOrders) ? '' : implode(',', $tmpOrders);
                }

                /**
                 * 去掉group中的day字段，因为不存在day字段
                 */
                if(!empty($options['group'])) {
                    $tmpGroups = explode(',', $options['group']);

                    if(($tmpKey = array_search('day', $tmpGroups)) !== false) {
                        unset($tmpGroups[$tmpKey]);
                        $options['group'] = implode(',', $tmpGroups);
                    }
                }

                $options = array_merge($options, array('table' => $tableName));

                $this->trueTableName = $tableName;

                unset($options['where']['day']);    //表中无day字段，用day主要是定位到对应日期的表上
            }
        }

        return parent::_parseOptions($options);
    }

    /**
     * getTableName
     * 根据$uid, $day返回表格完整名称
     *
     * @param mixed $uid
     * @param mixed $day
     * @return void
     */
    public function getTableName($uid, $day) {
        $timestamp  = strtotime($day);
        $tableIndex = $uid % self::TABLE_PARTITION_NUM;

        return 'd' . date('Ymd', $timestamp) . '.'. $this->tableName2 . '_' . $tableIndex;
    }

    /**
     * parseDayBetween
     * 分解day中的between条件
     *
     * @param mixed $options
     * @return void
     */
    protected function parseDayBetween(&$options) {
        $startDay       = $options['where']['day'][1][0];
        $endDay         = $options['where']['day'][1][1];
        $startTimestamp = strtotime($startDay);
        $endTimestamp   = strtotime($endDay);
        $tmpTimestamp   = $startTimestamp;
        $tmpDay         = $startDay;
        $uid = $options['where']['uid'];    //必须要有uid参数

        if($startDay == $endDay) {
            $options['table']    = $this->getTableName($uid, $startDay);
            $this->trueTableName = $options['table'];

            return true;
        }

        $order = $options['order'];
        $field = $options['field'];
        $limit = $options['limit'];
        unset($options['order']);
        unset($options['limit']);
        $distGroup = empty($options['group']) ? '' : $options['group'];

        /**
         * 去掉group中的day字段，day实际是不存在的
         * 但是union all中会动态生成一个day字段，所以在union all后可以用day进行group
         */
        if(!empty($options['group'])) {
            $tmpGroups = explode(',', $options['group']);

            if(($tmpKey = array_search('day', $tmpGroups)) !== false) {
                unset($tmpGroups[$tmpKey]);

                if(!empty($tmpGroups)) {
                    $options['group'] = implode(',', $tmpGroups);
                }
            }
        }

        /**
         * 去掉field中的day字段，后期会动态生成day字段
         */
        $tmpFields = explode(',', $options['field']);

        if(($tmpKey = array_search('day', $tmpFields)) !== false ) {
            unset($tmpFields[$tmpKey]);
            $options['field'] = implode(',', $tmpFields);
        }

        $distOptions    = $options;
        $firstExistsDay = null;

        while($tmpTimestamp <= $endTimestamp) {
            $tmpOptions = $distOptions;
            $tmpDay     = date('Y-m-d', $tmpTimestamp);
            $table      = $this->getTableName($uid, $tmpDay);
            $tmpTables  = explode('.', $table);

            /**
             * 检测表格是否存在，如果不存在则忽略
             */
            if(!checkTableIsExists($tmpTables[1], $tmpTables[0])) {
                $tmpTimestamp = strtotime('+1 day', $tmpTimestamp);

                continue;
            }

            if(empty($firstExistsDay)) {
                $firstExistsDay = $tmpDay;
            }

            $tmpOptions['field'] .= ", '" . date('Y-m-d', $tmpTimestamp) . "' AS day";

            /**
             * 第一个判断中的条件做为buildSelectSql()中原始条件
             */
            if($tmpDay == $startDay || $tmpDay == $firstExistsDay) {
                $options['table'] = $table;
                $options['field'] .= ", '" . date('Y-m-d', $tmpTimestamp) . "' AS day";
                unset($options['where']['day']);
                $this->trueTableName = $table;
            } else {
                $tmpOptions['table'] = $table;
                $tmpOptions['where']['uid'] = $uid;
                unset($tmpOptions['where']['day']);
                $sql = $this->db->buildSelectSql($tmpOptions);
            }

            $tmpTimestamp = strtotime('+1 day', $tmpTimestamp);

            if(!empty($sql)) {
                $this->union($sql, 1);
            }
        }

        $sql = $this->db->buildSelectSql($options);
        $this->options = array(
            'table' => "({$sql}) AS a",
            'field' => $field,
            'order' => $order,
            'limit' => $limit,
            'group' => empty($distGroup) ? '' : $distGroup,
        );
    }

    /**
     * buildSearchExpr 
     * 组装查询条件
     * 
     * @param mixed $d  查询数据，一般来源于$_GET或$_POST
     * @param mixed $field  可查询的字段对照表，其结构为array(array('表单项目名称' => '数据库字段名称'))
     * @access public
     * @return void 返回值为数组，参见方法内部注释
     */
    public function buildSearchExpr($d, $field = NULL) {
        $expr = array();
        $dao  = array();
        $sortExpr = 'view DESC';

        /**
         * 下标为表单中的项目名称，值为数据库中表的字段名称 
         */
        if(empty($field)) {
            $field = array(
                'day'     => 'day',
                'day2'    => 'day',
                'uid'     => 'uid',
                'plan_id' => 'plan_id',
            );
        }

        $day  = empty($d['day'])  ? date('Y-m-d') : trim($d['day']);
        $day2 = empty($d['day2']) ? null          : trim($d['day2']);

        if(!empty($day)) {
            if(!empty($day2)) {
                $a = strtotime($day);
                $b = strtotime($day2);

                if($a > $b) {
                    $day2 = $day;
                    $day  = date('Y-m-d', $b);
                }

                $expr['day'] = array('between', array($day, $day2));
            } else {
                $expr['day'] = $day;
            }
        }

        foreach($field as $k => $v) {
            $tmpExpr = null;
            $val     = isset($d[$k]) ? trim($d[$k]) : '';

            if(strlen($val) < 1) {
                continue;
            }

            switch($k) {
                case 'user_name' :
                    $expr['user_name'] = array('EXP', "LIKE '%{$val}%'");
                    break;

                case 'email' : 
                    $expr['email'] = array('EXP', "LIKE '%{$val}%'");
                    break;

                case 'day' :
                case 'day2':
                    break;

                default:
                    $expr[$v] = $d[$k];
            }

            if(!empty($tmpExpr)) {
                $expr['_string'] = empty($expr['_string'])
                                  ? $tmpExpr
                                  : $expr['_string'] . " AND {$tmpExpr}";
            }

            $dao[$k] = $d[$k];
        }

        if(!empty($d['sort']) && array_key_exists($d['sort'], $this->db->getFields($this->tableName))) {
            $sortdir = empty($d['sortdir'])                     ? 'DESC'   : strtoupper($d['sortdir']);
            $sortdir = in_array($sortdir, array('DESC', 'ASC')) ? $sortdir : 'DESC';

            if($d['sort'] == 'money') {
                $sort        = '(daymoney+weekmoney+monthmoney)';
                $dao['sort'] = 'money';
            } else {
                $sort        = $d['sort'];
                $dao['sort'] = $sort;
            }

            $sortExpr = "{$sort} {$sortdir}";

            $dao['sortdir'] = $sortdir;
        }

        if(empty($expr) && empty($dao)) {
            return false;
        }

        return array(
            'expr' => $expr,            //ThinkPHP查询条件表达式
            'sort' => $sortExpr,        //排序表达式
            'json' => json_encode($dao) //用于回填至查询表单的数据
        );
    }

    protected function _options_filter(&$options) {
    }

}
